using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace UnitTesting.Fixturing
{
	class ParamCountConstructorSelector<T> : ConstructorSelectorBase<T>
	{
		readonly bool _isStrict;
		readonly int _paramCount;

		internal bool IsStrict
		{
			get { return _isStrict; }
		}

		internal int ParamCount
		{
			get { return _paramCount; }
		}

		internal ParamCountConstructorSelector(bool isStrict, int paramCount)
		{
			_isStrict = isStrict;
			_paramCount = paramCount;
		}

		protected internal override ConstructorInfo Select(ConstructorInfo[] constructors)
		{
			return !_isStrict
			       	? SelectFirstOrDefault(constructors)
			       	: SelectSingleOrDefault(constructors);
		}

		ConstructorInfo SelectFirstOrDefault(IEnumerable<ConstructorInfo> constructors)
		{
			return constructors.FirstOrDefault(x => x.GetParameters().Length == _paramCount);
		}

		ConstructorInfo SelectSingleOrDefault(IEnumerable<ConstructorInfo> constructors)
		{
			try
			{
				return constructors.SingleOrDefault(x => x.GetParameters().Length == _paramCount);
			}
			catch (InvalidOperationException)
			{
				throw new TooManyMatchedConstructorException(typeof (T), _paramCount);
			}
		}
	}
}